#include <buola/chart/mappings/clogmapping.h>

namespace buola { namespace chart {

CLogMapping::CLogMapping()
{
    mMinSrc=0.1;
    mMaxSrc=1.0;
}

CLogMapping::~CLogMapping()
{
}

double CLogMapping::Map(double pV)
{
    if(pV<=0) pV=mMinSrc*(mMinSrc/mMaxSrc);
    return mMinDest+log(pV/mMinSrc)*mMult;
}

double CLogMapping::InverseMap(double pV)
{
    return mMinSrc*pow(M_E,(pV-mMinDest)/mMult);
}

int CLogMapping::GetTicks(std::vector<double> &pTicks,double pMinDist)
{
    int lMaxTicks=abs((int)floor((mMaxDest-mMinDest)/pMinDist));
    double lMinTickStep=pow(mMaxSrc/mMinSrc,1.0/lMaxTicks);
    
    pTicks.clear();
    
    if(lMinTickStep<2)
    {
        for(double lPos=pow(10,floor(log10(mMinSrc)));;lPos*=10)
        {
            if(2*lPos>mMaxSrc) 
                break;
            if(2*lPos>mMinSrc)
                pTicks.push_back(2*lPos);
            if(5*lPos>mMaxSrc)
                break;
            if(5*lPos>mMinSrc)
                pTicks.push_back(5*lPos);
            if(10*lPos>mMaxSrc)
                break;
            pTicks.push_back(10*lPos);
        }
    }
    else
    {
        double lStep=pow(10,ceil(log10(lMinTickStep)));
        for(double lPos=10*pow(10,floor(log10(mMinSrc)));lPos<mMaxSrc;lPos*=lStep)
            pTicks.push_back(lPos);
    }

    return 0;   
}

void CLogMapping::AutoScale(double pMin,double pMinPos,double pMax,
                                bool pNiceLimits,double pMinDist)
{
    mMinSrc=pMinPos;
    mMaxSrc=pMax;
    Update();
}

void CLogMapping::Update()
{
    if(mMinSrc<=0) mMinSrc=1;
    if(mMaxSrc<mMinSrc) mMaxSrc=mMinSrc*100;

    mMult=(mMaxDest-mMinDest)/log(mMaxSrc/mMinSrc);
}

/*namespace chart*/ } /*namespace buola*/ }
